﻿using log4net;
using Microsoft.AspNetCore.SignalR.Client;
using Service.Net.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;

namespace Service.Net.Manager
{
    public class NetManager : INetManager
    {
        private readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        public bool IsConnected { get; private set; }

        public event Action<bool> ConnectStatusChangedEvent;
        public event Action<string> MessageEvent;

        public HubConnection NetConnet;

        public async Task<bool> ConnectNet(ConnectModel model)
        {
            if (model != null)
            {
                if (!IsConnected)
                {
                    var reqmsg = new MultipartFormDataContent();
                    reqmsg.Headers.Add("ContentType", "multipart/form-data");//声明头部
                    reqmsg.Add(new StringContent(model.ClientId), "app_id");
                    reqmsg.Add(new StringContent(model.Secret), "app_secret");
                    var response = await new HttpClient().PostAsync($"http://{model.HostName}:{model.Port}/openapi/v1/authentication/access_token", reqmsg);
                    var result = await response.Content.ReadAsStringAsync();

                    var dict = JsonHelper.DeSerialize<Dictionary<string, object>>(result);
                    var ok = dict.TryGetValue("access_token", out var token);

                    NetConnet = new HubConnectionBuilder().WithUrl($"http://{model.HostName}:{model.Port}/openapi/v1/hub/login", (opts) =>
                    {
                        opts.Headers.Add("Authorization", new AuthenticationHeaderValue("Bearer", token?.ToString() ?? "").ToString());
                    }).WithAutomaticReconnect().Build();
                    NetConnet.On<string>("ReceiveMessage", msg =>
                    {
                        MessageEvent?.Invoke(msg);
                    });
                    await NetConnet.StartAsync();
                }
                RefrshConnectStatus(true);
            }
            else
            {
                _logger.Debug($"Mqtt connect info is null, nothing");
            }
            return IsConnected;
        }

        public Task SendMessage(string topic, string message)
        {
            return NetConnet.SendAsync(topic, message);
        }

        private void RefrshConnectStatus(bool isConnet)
        {
            IsConnected = isConnet;
            ConnectStatusChangedEvent?.Invoke(isConnet);
        }
    }
}
